Skip to content

Fix stray bin folder race on deleted .classpath (partial fix for flaky MavenProjectMetadataFileTest) - #3840

Closed
chagong wants to merge 1 commit into
eclipse-jdtls:mainfrom
chagong:fix/classpath-refresh-race
Closed

Fix stray bin folder race on deleted .classpath (partial fix for flaky MavenProjectMetadataFileTest)#3840
chagong wants to merge 1 commit into
eclipse-jdtls:mainfrom
chagong:fix/classpath-refresh-race

Conversation

@chagong

@chagong chagong commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

What

Fixes one confirmed root cause behind the long-standing flaky MavenProjectMetadataFileTest failures (e.g. seen in #3839's CI): a race between StandardProjectsManager.fileChanged()'s eager resource refresh and IBuildSupport.refresh()'s classpath recovery logic for DELETED .classpath events.

Root cause

fileChanged() called JDTUtils.getFileOrFolder(uriString), which eagerly calls IContainer#refreshLocal(DEPTH_ONE, null). For a deleted .classpath file, this notifies JDT Core's classpath machinery that the file is gone before IBuildSupport.refresh() gets a chance to recover/regenerate the correct classpath. In that window, JDT Core briefly falls back to a default classpath and creates a stray bin output folder — which is exactly the symptom asserted against in MavenProjectMetadataFileTest#testDeleteClasspath.

This matches long-standing reports in #1443 and #1251.

Fix

Resolve deleted .classpath files via JDTUtils.findFile() instead, which does not perform the premature refresh. IBuildSupport.refresh() already performs the equivalent (and correctly ordered) refresh once it has restored the classpath.

Verification

Reproduced locally via:

.\mvnw.cmd -o -pl org.eclipse.jdt.ls.tests -am integration-test "-Dtest=MavenProjectMetadataFileTest" "-DfailIfNoTests=false"

Confirmed this change eliminates the stray-bin-folder assertion failure, reproducibly across multiple runs.

Note: second, deeper issue remains

While investigating, I found a second, unrelated root cause affecting testMetadataFileSync and part of testDeleteClasspath — an EFS-redirect/resource-tree synchronization gap in org.eclipse.jdt.ls.filesystem (active when java.import.generatesMetadataFilesAtProjectRoot=false). I've documented detailed findings (including instrumented trace evidence from eclipse.jdt.core) in a follow-up issue rather than bundling an unverified fix here, since it needs live debugging to pin down precisely. This PR only contains the confirmed, verified fix.

StandardProjectsManager.fileChanged() called JDTUtils.getFileOrFolder(),
which eagerly refreshes the resource tree, before IBuildSupport.refresh()
had a chance to recover the classpath for a DELETED .classpath event.
This notified JDT Core's classpath machinery that the file was gone
before the recovery logic ran, causing JDT Core to briefly fall back to
a default classpath and create a stray bin output folder.

Resolve deleted .classpath files via JDTUtils.findFile() instead, which
does not perform the premature refresh; IBuildSupport.refresh() already
performs the equivalent refresh once the classpath has been restored.

Fixes the stray-bin-folder root cause behind the long-standing flaky
MavenProjectMetadataFileTest failures. See eclipse-jdtls#1443
and eclipse-jdtls#1251.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant